﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Collections.Generic;

namespace BrainTechLLC.Silverlight.Controls
{
    public static class TempExten
    {
        public static void HandleChange<T1, T2>(this DependencyObject d, DependencyPropertyChangedEventArgs e, Action<T1, T2> action, Action<T1> update) where T1 : DependencyObject
        {
            T1 ctrl = (T1)d;
            T2 val = (T2)e.NewValue;
            action(ctrl, val);
            update(ctrl);
        }

        public static T FindParent<T>(this FrameworkElement t) where T : FrameworkElement
        {
            if (t == null)
                return null;

            DependencyObject d = VisualTreeHelper.GetParent(t);

            if (d != null)
            {
                T ret = d as T;

                if (ret == null)
                    return (d as FrameworkElement).FindParent<T>();

                return ret;
            }

            return null;
        }

        public static void StretchListBox(this FrameworkElement t)
        {
            ContentPresenter p = t.FindParent<ContentPresenter>();

            if (p != null)
            {
                p.HorizontalAlignment = HorizontalAlignment.Stretch;
            }
        }

        public static bool EnsureVisibility(this UIElement c, bool visible)
        {
            if (c == null)
                return false;

            if (visible && c.Visibility == Visibility.Collapsed)
            {
                c.Visibility = Visibility.Visible;
                return true;
            }
            else if (!visible && c.Visibility == Visibility.Visible)
            {
                c.Visibility = Visibility.Collapsed;
                return true;
            }

            return false;
        }

        public static List<DependencyObject> GetAllChildren(this DependencyObject obj)
        {
            List<DependencyObject> results = new List<DependencyObject>();

            for (int n = 0; n < VisualTreeHelper.GetChildrenCount(obj); n++)
            {
                var child1 = VisualTreeHelper.GetChild(obj, n);

                if (child1 != null)
                    results.Add(child1);
            }

            return results;
        }


        public static List<DependencyObject> GetActualChildren(this DependencyObject p)
        {
            List<DependencyObject> results = new List<DependencyObject>();

            if (p is Border)
            {
                if ((p as Border).Child != null)
                    results.Add((p as Border).Child);
            }
            else if (p is Canvas)
            {
                results.AddRange((p as Canvas).GetAllChildren());
            }
            else if (p is Panel)
            {
                results.AddRange((p as Panel).GetAllChildren());
            }
            else if (p is ContentControl)
            {
                if ((p as ContentControl).Content != null && (p as ContentControl).Content is DependencyObject)
                    results.Add((p as ContentControl).Content as DependencyObject);
            }
            else if (p is ContentPresenter && (p as ContentPresenter).Content is DependencyObject)
            {
                if ((p as ContentPresenter).Content != null)
                    results.Add((p as ContentPresenter).Content as DependencyObject);
            }
            else
            {
                results.AddRange(p.GetAllChildren());
            }

            return results;
        }

        public static int ForEachRecursive<T>(this DependencyObject p, Action<T> action, Func<T, bool> filter) where T : class
        {
            int count = 0;

            if (p == null)
                return 0;

            if (p is Canvas)
                return ForEachRecursive<T>(p as Canvas, action, filter);
            else if (p is Panel)
                return ForEachRecursive<T>(p as Panel, action, filter);

            try
            {
                var results = p.GetActualChildren();

                for (int n = 0; n < results.Count; n++)
                {
                    var child1 = results[n];                    
                    
                    count += ForEachRecursive<T>(child1, action, filter);                    
                }
            }
            catch { }

            return 0;
        }

        public static int ForEachRecursive<T>(this Canvas p, Action<T> action, Func<T, bool> filter) where T : class
        {
            int count = 0;

            if (p == null)
                return 0;

            if (p is T)
            {
                if (filter == null || !filter(p as T))
                {
                    action(p as T);
                    count++;
                }
            }

            for (int n = 0; n < p.Children.Count; n++)
            {
                var child = p.Children[n];

                if (child is T)
                {
                    if (filter == null || !filter(child as T))
                    {
                        action(child as T);
                        count++;
                    }
                }

                Panel panelChild = child as Panel;
                if (panelChild != null)
                {
                    count += ForEachRecursive<T>(panelChild, action, filter);
                }
                else
                {
                    Canvas can = child as Canvas;

                    if (can != null)
                        count += ForEachRecursive<T>(can, action, filter);
                }

                ContentControl content = child as ContentControl;
                if (content != null && content.Content is Panel)
                {
                    count += ForEachRecursive<T>(content.Content as Panel, action, filter);
                }

                ContentPresenter presenter = child as ContentPresenter;
                if (presenter != null && presenter.Content is Panel)
                {
                    count += ForEachRecursive<T>(presenter.Content as Panel, action, filter);
                }
            }
            return count;
        }

        public static int ForEachRecursive<T>(this Panel p, Action<T> action, Func<T, bool> filter) where T : class
        {
            int count = 0;

            if (p == null)
                return 0;

            if (p is T)
            {
                if (filter == null || !filter(p as T))
                {
                    action(p as T);
                    count++;
                }
            }
            
            for (int n = 0; n < p.Children.Count; n++)
            {
                var child = p.Children[n];

                if (child is T)
                {
                    if (filter == null || !filter(child as T))
                    {
                        action(child as T);
                        count++;
                    }
                }

                Panel panelChild = child as Panel;
                if (panelChild != null)
                {
                    count += ForEachRecursive<T>(panelChild, action, filter);
                }
                else
                {
                    Canvas can = child as Canvas;

                    if (can != null)
                        count += ForEachRecursive<T>(can, action, filter);
                }

                ContentControl content = child as ContentControl;
                if (content != null && content.Content is Panel)
                {
                    count += ForEachRecursive<T>(content.Content as Panel, action, filter);
                }

                ContentPresenter presenter = child as ContentPresenter;
                if (presenter != null && presenter.Content is Panel)
                {
                    count += ForEachRecursive<T>(presenter.Content as Panel, action, filter);
                }

                ListBox lb = child as ListBox;
                if (lb != null)
                {
                    count += ForEachRecursive<T>(lb as Control, action, filter);
                }
            }
            return count;
        }
    }

    public class StringToTypeConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType.IsAssignableFrom(typeof(string));
        }
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            string text = value as string;
            if (text != null)
            {
                return Type.GetType(text);
            }
            return null;
        }
    }
}
